package lib.bone.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import cn.hutool.extra.pinyin.PinyinUtil;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.PageResultDTO;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.common.exception.BusinessException;
import lib.bone.system.dao.SysDeptDAO;
import lib.bone.system.domain.dto.dept.DeptAddDTO;
import lib.bone.system.domain.entity.SysDept;
import lib.bone.system.domain.vo.DeptVO;
import lib.bone.system.domain.vo.SysDeptBasic;
import lib.bone.system.service.SysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * @Author : kindear
 * @Date : 2021-12-29
 */
@Slf4j
@Service
public class SysDeptServiceImpl implements SysDeptService {


    @Autowired
    SysDeptDAO sysDeptDAO;

    @Override
    public Optional<SysDept> findByDeptName(String deptName) {
        return sysDeptDAO.findByDeptName(deptName);
    }

    @Override
    public List<SysDeptBasic> getAllDeptBasic() {
        return sysDeptDAO.getAllDeptBasic();
    }

    @Override
    public SysDept saveOne(SysDept sysDept) {
        // 新建记录不允许ID存在
        if (Validator.isNotEmpty(sysDept.getId())){
            throw new BusinessException(ResponseCodeConst.ERROR_PARAM);
        }
        String initial = PinyinUtil.getFirstLetter(sysDept.getDeptName(),"").substring(0,1);
        SysDept sysdept = new SysDept();
        BeanUtil.copyProperties(sysDept,sysdept,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        sysdept.setInitial(initial);
        return sysDeptDAO.save(sysdept);
    }

    @Override
    public SysDept updateOne(SysDept sysDept) {
        // 更新记录必须要求ID存在
        if (Validator.isEmpty(sysDept.getId())){
            throw new BusinessException(ResponseCodeConst.ERROR_PARAM);
        }
        String initial = PinyinUtil.getFirstLetter(sysDept.getDeptName(),"").substring(0,1);
        SysDept sysdept = new SysDept();
        BeanUtil.copyProperties(sysDept,sysdept,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        sysdept.setInitial(initial);
        return sysDeptDAO.save(sysdept);
    }

    @Override
    public List<SysDept> findByIds(List<Long> ids) {
        return sysDeptDAO.findByIdIn(ids);
    }

    @Override
    public PageResultDTO<SysDept> getAll(Pageable pageable, Example<SysDept> example) {
        return null;
    }



    @Override
    public ResponseDTO<SysDept> saveDept(DeptAddDTO deptAddDTO) {

        /** 初始化构建 **/
        SysDept sysDept = new SysDept();
        BeanUtil.copyProperties(deptAddDTO,sysDept, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        /**
         * 如果是null 赋值为0
         */
        if(Validator.isEmpty(deptAddDTO.getParentId())){
            deptAddDTO.setParentId(0L);
        }
        Optional<SysDept> parentOp = sysDeptDAO.findById(deptAddDTO.getParentId());

        if(parentOp.isPresent()){
            /** 设置祖先 和 父部门 --ignore **/
            sysDept.setParent(parentOp.get());
            SysDept parent = new SysDept();
            // 隔离状态 -- 脱离托管为游离态
            BeanUtil.copyProperties(parentOp.get(),parent);
            List<Long> ancestors = parent.getAncestors();
            ancestors.add(deptAddDTO.getParentId());
            //log.info(ancestors.toString());
            sysDept.setAncestors(ancestors);
            //log.info(parentOp.get().toString());
            //sysDept.setParent(parent);

        }else {
            List<Long> ancestors = new ArrayList<>();
            ancestors.add(0L);
            sysDept.setAncestors(ancestors);
        }
        /**
         * 返回封包数据
         */
        return ResponseDTO.succData(sysDeptDAO.save(sysDept));
    }

//    @Override
//    public ResponseDTO updateOneDept(SysDept sysDept) {
//        return null;
//    }

    @Override
    @Transactional
    public ResponseDTO deleteById(Long deptId) {
        Optional<SysDept> sysDeptOp = sysDeptDAO.findById(deptId);

        if(!sysDeptOp.isPresent()) {
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"ID:["+deptId+"]对应部门不存在");
        }
        SysDept parent = sysDeptOp.get().getParent();
        // 需要移除关系被维护端的关联关系
        if(Validator.isNotEmpty(parent)){
            parent.getChildren().remove(sysDeptOp.get());
        }
        sysDeptDAO.deleteById(deptId);
        return ResponseDTO.succMsg("删除成功");
    }

//    @Override
//    public Optional<SysDept> getOneDept(Long deptId) {
//        return sysDeptDAO.findById(deptId);
//    }

    @Override
    public Optional<SysDept> getById(Long id) {
        return sysDeptDAO.findById(id);
    }

    /**
     * 构建选择器 -- 清理无用数据
     */
    @Override
    public List<DeptVO> buildDeptTree(List<SysDept> depts) {

        List<DeptVO> deptTree = new ArrayList<>();
        for(SysDept sysDept:depts){

            DeptVO deptVO = new DeptVO();
            deptVO.setDeptName(sysDept.getDeptName());
            deptVO.setId(sysDept.getId());
            Set<SysDept> cdepts = sysDept.getChildren();
            if(Validator.isNotEmpty(cdepts) && cdepts.size() > 0){
                deptVO.setChildren(buildDeptTree(new ArrayList<>(cdepts)));
            }
            deptTree.add(deptVO);
        }
        return deptTree;
    }

    //    @Override
//    public List<SysDept> findByExample(Example<SysDept> example) {
//        return sysDeptDAO.findAll(example);
//    }
//
//    @Override
//    public List<SysDept> findByParentId(Long parentId) {
//        return sysDeptDAO.findByParentId(parentId);
//    }



    @Override
    public List<SysDept> findByParent(SysDept parent) {
        if(Validator.isEmpty(parent)){
            return sysDeptDAO.findByParentIsNull();
        }else {
            Example<SysDept> example = Example.of(parent);
            return sysDeptDAO.findAll(example);
        }
    }
}
